#!/bin/bash

# 自动添加www子域名函数
add_www_subdomain() {
    local domains=($1)
    local result=()

    for domain in "${domains[@]}"; do
        result+=("$domain")
        if [[ ! "$domain" =~ \* ]] && [[ "$domain" =~ ^[^.]+\.([a-zA-Z]{2,})$ ]]; then
            www_domain="www.$domain"
            [[ " ${result[@]} " =~ " $www_domain " ]] || result+=("$www_domain")
        fi
    done

    echo "${result[@]}"
}

# 初始化路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CA_CERT="$SCRIPT_DIR/ssl_certs/Local_CA.crt"
CA_KEY="$SCRIPT_DIR/ssl_certs/Local_CA.key"

# 显示菜单
clear
echo "SSL证书生成脚本"
echo "------------------------"
echo "1) 单域名（自动添加www）"
echo "2) 多域名（自动添加各域名www）"
echo "3) 通配符域名（如*.example.com）"
echo "4) 子域通配符（如*.sub.example.com）"
read -p "请选择证书类型 [1-4]: " CHOICE

# 验证选项
if [[ ! "$CHOICE" =~ ^[1-4]$ ]]; then
    echo "错误：无效选项"
    exit 1
fi

# 有效期处理
read -p "输入有效期（年，默认3）: " YEARS
YEARS=${YEARS:-3}
[[ "$YEARS" =~ ^[0-9]+$ ]] || {
    echo "错误：必须输入数字";
    exit 1
}
DAYS=$((YEARS * 365))

# 域名处理逻辑
case $CHOICE in
1)
    read -p "输入主域名（如example.com）: " DOMAIN
    [[ "$DOMAIN" =~ ^[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$ ]] || {
        echo "错误：域名格式无效"; exit 1
    }
    SAN_LIST=($(add_www_subdomain "$DOMAIN"))
    ;;
2)
    read -p "输入多个域名（空格/逗号分隔）: " INPUT
    RAW_LIST=($(echo "$INPUT" | tr ',' ' ' | xargs -n1 | sort -u))
    VALID_LIST=()
    for d in "${RAW_LIST[@]}"; do
        if [[ "$d" =~ ^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
            VALID_LIST+=("$d")
        else
            echo "警告：忽略无效域名 $d"
        fi
    done
    [ ${#VALID_LIST[@]} -eq 0 ] && {
        echo "错误：无有效域名输入"; exit 1
    }
    SAN_LIST=($(add_www_subdomain "${VALID_LIST[*]}"))
    ;;
3)
    read -p "输入通配符域名（如*.example.com）: " DOMAIN
    [[ "$DOMAIN" =~ ^\*\.[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$ ]] || {
        echo "错误：通配符格式应为*.example.com"; exit 1
    }
    SAN_LIST=("$DOMAIN")
    ;;
4)
    read -p "输入子域通配符（如*.dev.example.com）: " DOMAIN
    [[ "$DOMAIN" =~ ^\*\.[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+){2,}$ ]] || {
        echo "错误：格式应为*.sub.example.com"; exit 1
    }
    SAN_LIST=("$DOMAIN")
    ;;
esac

# 创建存储目录
CERT_NAME=$(echo "${SAN_LIST[0]}" | tr '*.' 'w_' | cut -c1-30)
CERT_DIR="$SCRIPT_DIR/ssl_certs/${CERT_NAME}_$(date +%Y%m%d)"
mkdir -p "$CERT_DIR" || {
    echo "目录创建失败";
    exit 1
}

# 生成SAN配置
SAN_CONFIG=""
for ((i=0; i<${#SAN_LIST[@]}; i++)); do
    SAN_CONFIG+="DNS.$((i+1)) = ${SAN_LIST[i]}"$'\n'
done

# 生成OpenSSL配置
CONFIG_FILE="${CERT_DIR}/openssl.cnf"
cat > "$CONFIG_FILE" <<EOF
[req]
default_bits = 2048
encrypt_key = no
default_md = sha256
prompt = no
distinguished_name = dn
req_extensions = req_ext
x509_extensions = v3_req

[dn]
C = CN
ST = Beijing
L = Beijing
O = Local Development
OU = Local Development
CN = ${SAN_LIST[0]}

[req_ext]
subjectAltName = @alt_names
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[v3_req]
subjectAltName = @alt_names
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[alt_names]
$SAN_CONFIG
EOF

# 生成CA证书（如果不存在）
if [ ! -f "$CA_CERT" ]; then
    openssl req -x509 -newkey rsa:2048 -nodes \
        -keyout "$CA_KEY" \
        -out "$CA_CERT" \
        -subj "/CN=Local Development Root CA" \
        -days 3650 >/dev/null 2>&1
fi

# 生成服务器证书
openssl req -new -newkey rsa:2048 -nodes \
    -keyout "${CERT_DIR}/server.key" \
    -out "${CERT_DIR}/server.csr" \
    -config "$CONFIG_FILE" >/dev/null 2>&1 || {
    echo "证书请求生成失败";
    rm -rf "$CERT_DIR";
    exit 1
}

openssl x509 -req \
    -in "${CERT_DIR}/server.csr" \
    -CA "$CA_CERT" \
    -CAkey "$CA_KEY" \
    -CAcreateserial \
    -out "${CERT_DIR}/server.crt" \
    -days "$DAYS" \
    -extfile "$CONFIG_FILE" \
    -extensions v3_req >/dev/null 2>&1 || {
    echo "证书签发失败";
    rm -rf "$CERT_DIR";
    exit 1
}

# 清理和权限设置
rm -f "$CONFIG_FILE" "${CERT_DIR}/server.csr"
chmod 400 "${CERT_DIR}/server.key"
chmod 444 "${CERT_DIR}/server.crt"

# 输出结果
echo -e "\n证书生成成功！"
echo "存储路径：$CERT_DIR"
echo -e "\n包含域名："
openssl x509 -in "${CERT_DIR}/server.crt" -noout -text | grep 'DNS:' | awk '{gsub(/,/,"\n"); print}'

echo -e "\n后续步骤："
echo "1. 安装CA证书：sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain \"$CA_CERT\""
echo "2. 服务器配置使用："
echo "   - 证书: ${CERT_DIR}/server.crt"
echo "   - 私钥: ${CERT_DIR}/server.key"
